/**
 * BulkSMSXCAPSbb
 * 
 * The XCAP enabled SBB for the bulk SMS service.
 * The SBB is invoked by prioritisation and may be required to chnage the parameters in the request i.e. resolution of group names to recipients
 */
package org.convergence.services.slee.bulksms.xcap;
/**
 * @author mtsietsi
 *
 */
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletResponse;
import javax.slee.ActivityContextInterface;
import javax.slee.RolledBackContext;
import javax.slee.Sbb;
import javax.slee.SbbContext;
import javax.slee.SbbLocalObject;
import javax.slee.facilities.Tracer;

import net.java.slee.resource.http.events.HttpServletRequestEvent;

import org.mobicents.slee.SbbContextExt;
import org.mobicents.slee.resource.xcapclient.XCAPClientResourceAdaptorSbbInterface;
import org.mobicents.xcap.client.XcapResponse;
import org.mobicents.xcap.client.auth.Credentials;
import org.mobicents.xcap.client.uri.AttributeSelectorBuilder;
import org.mobicents.xcap.client.uri.DocumentSelectorBuilder;
import org.mobicents.xcap.client.uri.ElementSelectorBuilder;
import org.mobicents.xcap.client.uri.UriBuilder;

import org.openxdm.xcap.client.appusage.resourcelists.jaxb.EntryType;
import org.openxdm.xcap.client.appusage.resourcelists.jaxb.DisplayNameType;
import org.openxdm.xcap.client.appusage.resourcelists.jaxb.ListType;
import org.openxdm.xcap.client.appusage.resourcelists.jaxb.ObjectFactory;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

public abstract class BulkSMSXCAPSbb implements Sbb {
	private SbbContextExt sbbContext; // This SBB's SbbContext
	private static Tracer tracer;
	private String strAuthUser;
	
	// **** Variables from the SBB environmental entries
    private String strServerAddress;
    private String strServerPort;
    private String strServerXcapRoot;
    private String strDefaultDocument;
    
    // **** Variables from the parent SBB
    private String strUsername;
    private String strPassword;
    private String strType;
    private String strOp;
    
    private String localTo;
    private String localName;
	private String localNewName;
	private String localNumber;
	private String localNewNumber;
	private String localGroup;
	private String localNewGroup;
	
	/**
     * static jaxb context for example pojos
     */
    private static JAXBContext jAXBContext = initJAXBContext();
    private static JAXBContext initJAXBContext() {
            try {
                    return JAXBContext.newInstance("org.openxdm.xcap.client.appusage.resourcelists.jaxb");
            } catch (JAXBException e) {
                    System.out.println("unable to init jaxb context");
                    e.printStackTrace();
                    return null;
            }
    }
    
    /* sending the response back to the requesting client */
    HttpServletRequestEvent httpEvent;
   
	
	// **** SLEE Children
	//public abstract ChildRelationExt getXDMClientChildRelation();

	// **** Activity Context Interface
    public abstract  XcapSbbActivityContextInterface asSbbActivityContextInterface(ActivityContextInterface aci);
    
    // ***** XCAP stuff
    private XCAPClientResourceAdaptorSbbInterface ra = null;
    private XcapResponse xcapResponse = null;
    private Credentials credentials;
	
    /**** SLEE ACTION HANDLERS ****/
    
    /*
	 * onServiceStartedEvent: invoked when the the SBB is loaded
	 * 						
	 * in: 
	 * 		ServicesStartedEvent: the type of event triggered by the SLEE when the SBB is loaded
	 * 		ActivityContextInterface: the activity context interface associated with the event 
	 */
	public void onServiceStartedEvent(javax.slee.serviceactivity.ServiceStartedEvent event, XcapSbbActivityContextInterface aci) {
		tracer.info("Bulk SMS XCAP Service Started");
	}
	
	/*
	 * (non-Javadoc)
	 * @see javax.slee.Sbb#setSbbContext(javax.slee.SbbContext)
	 * setSbbContext:	beginning of the life cycle of the SBB
	 * 				: 	here we set the tracer and grab values of server parameters that are configured in the <entry> tags in the sbb-jar.xml file
	 */
	public void setSbbContext(SbbContext context) { 
		this.sbbContext = (SbbContextExt) context;
		tracer = sbbContext.getTracer(getClass().getSimpleName());
		/* get variables in the SBB environment entries */
		/* please see sbb.xml file */
		try {
			Context myEnv = (Context) new InitialContext().lookup("java:comp/env");
			this.strServerAddress = (String) myEnv.lookup("serverAddress");
			this.strServerPort = (String) myEnv.lookup("serverPort");
			this.strServerXcapRoot = (String) myEnv.lookup("serverXcapRoot");
			this.strDefaultDocument = (String) myEnv.lookup("defaultDocument");
			this.ra = (XCAPClientResourceAdaptorSbbInterface) myEnv.lookup("slee/resources/xcapclient/2.0/sbbrainterface");

		} catch (NamingException e) {
			tracer.info("Naming exception in setSbbContext");
			e.printStackTrace();
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see javax.slee.Sbb#unsetSbbContext()
	 */
	public void unsetSbbContext() { 
		this.sbbContext = null; 
	}
	
	public void sbbCreate() throws javax.slee.CreateException {}
	public void sbbPostCreate() throws javax.slee.CreateException {}
	public void sbbActivate() {}
	public void sbbPassivate() {}
	public void sbbRemove() {}
	public void sbbLoad() {}
	public void sbbStore() {}
	public void sbbExceptionThrown(Exception exception, Object event, ActivityContextInterface activity) {}
	public void sbbRolledBack(RolledBackContext context) {}
	
	/**** HTTP ACTION HANDLERS ****/
	/*
	 * OnGet: process the GET operation from an external system and invoke the proper management method depending on the type parameter
	 * in:
	 * 		HttpServletRequestEvent: the http type event from the RA
	 * 		ActivityContextInterface: the activity context associated with the event
	 */
	public void onGet(HttpServletRequestEvent event, XcapSbbActivityContextInterface aci) {
		tracer.info("Received GET operation");
		
		/* initialise local vars to aci attributes */
		assignParams(aci);
		
		if(aci.getProcessedByPredecessor()) {
			tracer.info("Processed by Predecessor");
			/* assign the HTTP Request event object to be used later to send error response to the external system */
			httpEvent = event;
			
			if(aci.getTypeInXcap().compareTo("document") == 0 || aci.getTypeInXcap().compareTo("group") == 0 ||
						aci.getTypeInXcap().compareTo("contact") == 0) {
				
				/* manage a contact list (document) */
				if(aci.getTypeInXcap().compareTo("document") == 0)
				manageDocument(aci.getUsernameInXcap(), aci.getPasswordInXcap(), aci.getOpInXcap());
				
				/* manage a group */
				else if(aci.getTypeInXcap().compareTo("group") == 0)
					manageGroup(aci.getUsernameInXcap(), aci.getPasswordInXcap(), aci.getOpInXcap(), aci.getGroupInXcap(), aci.getNewGroupInXcap());
				
				/* manage a contact */
				else if(aci.getTypeInXcap().compareTo("contact") == 0) {
					manageContact(aci.getUsernameInXcap(), aci.getPasswordInXcap(), aci.getOpInXcap(), aci.getNameInXcap(), 
								aci.getNumberInXcap(), aci.getGroupInXcap(), aci.getNewNameInXcap(), aci.getNewNumberInXcap());
				}
				
				/* this request must not be processed any further i.e. by the SMS and billing services */
				aci.setProcessedByMe(false);
				SbbLocalObject sbbLocalObject = sbbContext.getSbbLocalObject();
		        aci.detach(sbbLocalObject);
			}
			/* manage an sms */
			else if(aci.getTypeInXcap().compareTo("sms") == 0) {
				manageSmsRecipients(aci.getUsernameInXcap(), aci.getPasswordInXcap(), aci.getTypeInXcap(), aci.getGroupInXcap(), aci);
			
				/* set by attribute and detach from activity context */
				aci.setProcessedByMe(true);
				SbbLocalObject sbbLocalObject = sbbContext.getSbbLocalObject();
		        aci.detach(sbbLocalObject);
			}
		}
		else {
			/* the predecessor will not allow this request to be handled at this time */
			tracer.info("Not processed by Predecessor");
			aci.setProcessedByMe(false);
			SbbLocalObject sbbLocalObject = sbbContext.getSbbLocalObject();
	        aci.detach(sbbLocalObject);
		}
	}
	
	/**** XCAP CALLBACK HANDLERS ****/
	
	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.enabler.xdmc.XDMClientParent#getResponse(java.net.URI, int, java.lang.String, java.lang.String, java.lang.String)
	 */
	public void getResponse(URI uri, int responseCode, String mimetype, String content, String eTag) {
		tracer.info("getResponse(" + uri + ", " + responseCode + ", " + mimetype + ", \n" + content + ", " + eTag + ")");
		int counter = 0;
		String entryNumber;
		String entryURI = new String();
		
		
		if(responseCode == 200) {
			StringReader reader = new StringReader(content);
			ListType listType = null;
			try {
				listType = (ListType) jAXBContext.createUnmarshaller().unmarshal(reader);
			} catch (JAXBException e) {
				tracer.severe("Unable to unmarshal the string");
				e.printStackTrace();
			}
			finally{
				reader.close();
				if(listType.getName().compareTo(localGroup) == 0) {
					// got the match for the sought contact group
					List<?> list = listType.getListOrExternalOrEntry();
					if(list.size() > 0) {
						counter = 0;
						while(counter < list.size()) {
							EntryType entry = (EntryType)((JAXBElement<?>)list.get(counter)).getValue();
							entryURI = (String) entry.getUri();
							int indexOfColon = entryURI.indexOf(":");
							int indexOfAt = entryURI.indexOf("@");
							entryNumber = entryURI.substring(indexOfColon+1, indexOfAt);
							tracer.info(entryNumber);
							counter++;
						}
					}
				}
				else{
					tracer.info("did not get the right list type");
				}
			}	
			processHttpRequest(httpEvent, "GET operation successful");
		}
		else
			processHttpRequest(httpEvent, "GET operation was not successful");
	}
	
	/*
	 * manageSMSReceipients: manage an SMS request from the perspective of converting group names into numbers, and append to the to parameter
	 */
	private void manageSmsRecipients(String username, String password, String to, String group, XcapSbbActivityContextInterface aci ) {
		Credentials credentials;
		
		String documentSelector;
		String elementSelector;
		String authUser;
		
		UriBuilder uriBuilder;
		URI elementURI;
		
		int counter = 0;
		String entryNumber;
		String entryURI = new String();
		String toInXcap = null;
		
		/* we only need to resolve recipients from XCAP if a group is specified, else we just use to parameter */
		if(group != null) {
			try {
				/* initialise variables */
				authUser = setAuthUser(username, strServerAddress);
				credentials = ra.getCredentialsFactory().getHttpDigestCredentials(authUser,password);
				documentSelector = DocumentSelectorBuilder.getUserDocumentSelectorBuilder(
		                "resource-lists", authUser, strDefaultDocument).toPercentEncodedString();
				
				elementSelector = new ElementSelectorBuilder()
						.appendStepByName("resource-lists")
						.appendStepByAttr("list", "name", group)
						.toPercentEncodedString();
		
				uriBuilder = new UriBuilder()
						.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
						.setXcapRoot("/"+strServerXcapRoot+"/")
						.setDocumentSelector(documentSelector)
						.setElementSelector(elementSelector);
		
				elementURI = uriBuilder.toURI();
				xcapResponse  = ra.get(elementURI, null, credentials);
				
				if(xcapResponse != null) {
					if(xcapResponse.getCode() == 200) {
						StringReader stringReader = new StringReader(xcapResponse.getEntity().getContentAsString());
	                    ListType listType = null;
	                    try {
	                            listType = (ListType) jAXBContext.createUnmarshaller().unmarshal(stringReader);
	                    }
	                    catch (Exception e) {
	                            tracer.severe("unable to unmarshall response content",e);
	                    }
	                    stringReader.close();
	                    if(listType != null && listType.getName().equals(localGroup)) {
	                    	List<?> list = listType.getListOrExternalOrEntry();
	    					if(list.size() > 0) {
	    						counter = 0;
	    						toInXcap = localTo;
	    						while(counter < list.size()) {
	    							EntryType entry = (EntryType)((JAXBElement<?>)list.get(counter)).getValue();
	    							entryURI = (String) entry.getUri();
	    							int indexOfColon = entryURI.indexOf(":");
	    							int indexOfAt = entryURI.indexOf("@");
	    							entryNumber = entryURI.substring(indexOfColon+1, indexOfAt);
	    							
	    							if(toInXcap == null) toInXcap = entryNumber;
	    							else toInXcap = toInXcap + "+"+entryNumber;
	    							
	    							counter++;
	    						}
	    						aci.setToInXcap(toInXcap);
	    					}
	                    }
	                    else {
	                    	tracer.severe("Missed the group somehow!!!");
	                    }
					}
					else {
						tracer.severe("Did not get success response from XCAP server");
					}
				}
				else{
					tracer.severe("Xcap response was null!!");
				}
			}
			catch (URISyntaxException e) {
				tracer.severe("URI Syntax Exception");
				e.printStackTrace();
			}
			catch(IOException io) {
				tracer.severe("failed to get user doc", io);
			}
		}
	}
	
	/****** Convenience Methods *******/
	
	/*
	 * manageContact: manages all operations pertaining to contact manipulation: (creation and deletion)
	 */
	private void manageContact(String username, String password, String operation, String name, 
			String number, String group, String newName, String newNumber) {
		Credentials credentials;
		
		String documentSelector;
		String elementSelector;
		String attributeSelector;
		String content;
		String authUser;
		String entryUser;
		
		UriBuilder uriBuilder;
		URI elementURI;
		
		try{
			authUser = setAuthUser(username, strServerAddress);
			credentials = ra.getCredentialsFactory().getHttpDigestCredentials(authUser,password);
			documentSelector = DocumentSelectorBuilder.getUserDocumentSelectorBuilder(
	                "resource-lists", authUser, strDefaultDocument).toPercentEncodedString();
			
			if(operation.compareTo("add") == 0) {
				// add a new contact
				entryUser = "sip:"+number+"@"+strServerAddress;
				elementSelector = new ElementSelectorBuilder()
					.appendStepByName("resource-lists")
					.appendStepByAttr("list", "name", group)
					.appendStepByAttr("entry", "uri", entryUser)
					.toPercentEncodedString();
				
				uriBuilder = new UriBuilder()
					.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
					.setXcapRoot("/"+strServerXcapRoot+"/")
					.setDocumentSelector(documentSelector)
					.setElementSelector(elementSelector);
				
				elementURI = uriBuilder.toURI();
				content = "\n<entry uri=\""+entryUser+"\" xmlns=\"urn:ietf:params:xml:ns:resource-lists\">"+
								"\n<display-name>"+name+"</display-name>"+
						  "\n</entry>";

				xcapResponse = ra.put(elementURI, "application/xcap-el+xml", content, null, credentials);
				tracer.info("Response for contact add: "+xcapResponse.getCode());
			}
			
			else if(operation.compareTo("edit") == 0) {
				entryUser = "sip:"+number+"@"+strServerAddress;
					
					//changing the display name
					if(newName != null) {
						elementSelector = new ElementSelectorBuilder()
						.appendStepByName("resource-lists")
						.appendStepByAttr("list", "name", group)
						.appendStepByAttr("entry", "uri", entryUser)
						.toPercentEncodedString();
						
						uriBuilder = new UriBuilder()
						.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
						.setXcapRoot("/"+strServerXcapRoot+"/")
						.setDocumentSelector(documentSelector)
						.setElementSelector(elementSelector);
						
						elementURI = uriBuilder.toURI();
						
						content = "<entry uri=\""+entryUser+"\" xmlns=\"urn:ietf:params:xml:ns:resource-lists\">"+
								"\n<display-name>"+newName+"</display-name>"+
							"\n</entry>";
						
						tracer.info("Inserting "+content);
						xcapResponse = ra.put(elementURI, "application/xcap-el+xml", content, null, credentials);
						tracer.info("Response for contact name edit: "+xcapResponse.getCode());
					}
					//changing the number
					else if(newNumber != null) {
						/*elementSelector = new ElementSelectorBuilder()
						.appendStepByName("resource-lists")
						.appendStepByAttr("list", "name", group)
						.appendStepByAttr("entry", "uri", entryUser)
						.toPercentEncodedString();
						
						attributeSelector = new AttributeSelectorBuilder("uri").toString();
						
						uriBuilder = new UriBuilder()
						.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
						.setXcapRoot("/"+strServerXcapRoot+"/")
						.setDocumentSelector(documentSelector)
						.setElementSelector(elementSelector)
						.setTerminalSelector(attributeSelector);
						
						elementURI = uriBuilder.toURI();
						tracer.info(elementURI.toString());
						
						
						entryUser = "sip:"+newNumber+"@"+strServerAddress;
						content = "uri=\""+entryUser+"\"";
				
						tracer.info("Inserting "+content);
						xcapResponse = ra.put(elementURI, "application/xcap-att+xml", content, null, credentials);
						tracer.info("Response for contact number edit: "+xcapResponse.getCode());*/
					}
			}
			else if(operation.compareTo("del") == 0) {
				//delete an existing contact
				entryUser = "sip:"+number+"@"+strServerAddress;
				elementSelector = new ElementSelectorBuilder()
					.appendStepByName("resource-lists")
					.appendStepByAttr("list", "name", group)
					.appendStepByAttr("entry", "uri", entryUser)
					.toPercentEncodedString();
				
				uriBuilder = new UriBuilder()
					.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
					.setXcapRoot("/"+strServerXcapRoot+"/")
					.setDocumentSelector(documentSelector)
					.setElementSelector(elementSelector);
				
				elementURI = uriBuilder.toURI();
				xcapResponse = ra.delete(elementURI, null, credentials);
				tracer.info("Response for contact delete: "+xcapResponse.getCode());
			}
		}
		catch (URISyntaxException e) {
			tracer.severe("URI Syntax Exception");
			e.printStackTrace();
		}
		catch(IOException io){
			tracer.severe("failed to create user doc", io);
		}
	}
	
	/*
	 * manageGroup: manages all operations pertaining to group manipulation: (creation and deletion)
	 */
	private void manageGroup(String username, String password, String operation, String group, String newGroup) {
		Credentials credentials;
		
		String documentSelector;
		String elementSelector;
		String content;
		String authUser;
		
		UriBuilder uriBuilder;
		URI elementURI;
		
		try{
			authUser = setAuthUser(username, strServerAddress);
			credentials = ra.getCredentialsFactory().getHttpDigestCredentials(authUser,password);
			documentSelector = DocumentSelectorBuilder.getUserDocumentSelectorBuilder(
	                "resource-lists", authUser, strDefaultDocument).toPercentEncodedString();
			
			if(operation.compareTo("add") == 0) {
				// add a new group to contact list
				elementSelector = new ElementSelectorBuilder()
						.appendStepByName("resource-lists")
						.appendStepByAttr("list", "name", group)
						.toPercentEncodedString();
				
				uriBuilder = new UriBuilder()
						.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
						.setXcapRoot("/"+strServerXcapRoot+"/")
						.setDocumentSelector(documentSelector)
						.setElementSelector(elementSelector);
				
				elementURI = uriBuilder.toURI();
				
				content = "<list xmlns=\"urn:ietf:params:xml:ns:resource-lists\" name=\""+group+"\"/>";
				xcapResponse = ra.put(elementURI, "application/xcap-el+xml", content, null, credentials);
				tracer.info("Response for group add: "+xcapResponse.getCode());
			}
			else if(operation.compareTo("del") == 0) {
				// delete group
				elementSelector = new ElementSelectorBuilder()
					.appendStepByName("resource-lists")
					.appendStepByAttr("list", "name", group)
					.toPercentEncodedString();
	
				uriBuilder = new UriBuilder()
					.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
					.setXcapRoot("/"+strServerXcapRoot+"/")
					.setDocumentSelector(documentSelector)
					.setElementSelector(elementSelector);
	
				elementURI = uriBuilder.toURI();
		
				content = "<list xmlns=\"urn:ietf:params:xml:ns:resource-lists\" name=\""+group+"\"/>";
				xcapResponse = ra.delete(elementURI, null, credentials);
				tracer.info("Response for group delete: "+xcapResponse.getCode());
			}
		}
		catch (URISyntaxException e) {
			tracer.severe("URI Syntax Exception");
			e.printStackTrace();
		}
		catch(IOException io){
			tracer.severe("failed to create user doc", io);
		}
	}
	
	/*
	 * manageDocument: manages all operations pertaining to document manipulation: (creation and deletion)
	 */
	private void manageDocument(String username, String password, String operation) {
		Credentials credentials;
		
		String authUser;
		String documentSelector;
		String exampleContent;
		
		UriBuilder uriBuilder;
		URI documentURI;
		
		try{
			
			authUser = setAuthUser(username, strServerAddress);
			credentials = ra.getCredentialsFactory().getHttpDigestCredentials(authUser,password);
			documentSelector = DocumentSelectorBuilder.getUserDocumentSelectorBuilder(
	                "resource-lists", authUser, strDefaultDocument).toPercentEncodedString();
			
			uriBuilder =  new UriBuilder()
					.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
					.setXcapRoot("/"+strServerXcapRoot+"/")
					.setDocumentSelector(documentSelector);
			
			documentURI = uriBuilder.toURI();
			exampleContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
				        "\n<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\">" +
				        	"\n<list xmlns=\"urn:ietf:params:xml:ns:resource-lists\" name=\"Ungrouped\"/>" +
				        "\n</resource-lists>";
			
			if(operation.compareTo("add") == 0) {
				xcapResponse = ra.put(documentURI, "application/resource-lists+xml", exampleContent, null, credentials);
				if(xcapResponse.getCode() == 200) 
					tracer.info("Successfully inserted XCAP document. Response code: "+ xcapResponse.getCode());
				else if(xcapResponse.getCode() == 201)	
					tracer.info("Successfully created XCAP document. Response code: "+ xcapResponse.getCode());
				else 
					tracer.info("Unsuccessful insertion/creation attempt for XCAP document. Response code: "+xcapResponse.getCode());
			}
			
			else if(operation.compareTo("get") == 0) {
				xcapResponse  = ra.get(documentURI, null, credentials);
				if(xcapResponse.getCode() == 200) {
					tracer.info("Successfully retrieved XCAP document. Response code: "+ xcapResponse.getCode());
					String content = xcapResponse.getEntity().getContentAsString();
					tracer.info(content);
				}
				else if (xcapResponse.getCode() == 404)
					tracer.info("Document not found. Response code: "+xcapResponse.getCode());
				
				else 
					tracer.info("Unsuccessful document retrieval attempt. Response code: "+xcapResponse.getCode());
			}
			
			else if(operation.compareTo("del") == 0) {
				xcapResponse  = ra.delete(documentURI, null, credentials);
				if(xcapResponse.getCode() == 200) {
					tracer.info("Successful deletion of XCAP document");
				}
				else if(xcapResponse.getCode() == 404){
					tracer.info("Document not found. Response code: "+xcapResponse.getCode());
				}
			}
		}
		catch (URISyntaxException e) {
			tracer.severe("URI Syntax Exception");
			e.printStackTrace();
		}
		catch(IOException io){
			tracer.severe("failed to create user doc", io);
		} 
	}
	
	public UriBuilder getUriBuilder(String documentSelector) {
		UriBuilder uriBuilder = new UriBuilder()
					.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
					.setXcapRoot("/"+strServerXcapRoot+"/")
					.setDocumentSelector(documentSelector);
		return uriBuilder;
	}
	
	public UriBuilder getUriBuilder(String documentSelector, String elementSelector) {
		UriBuilder uriBuilder = new UriBuilder()
					.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
					.setXcapRoot("/"+strServerXcapRoot+"/")
					.setDocumentSelector(documentSelector)
					.setElementSelector(elementSelector);
		return uriBuilder;
	}
	
	public UriBuilder getUriBuilder(String documentSelector, String elementSelector, String attributeSelector) {
		UriBuilder uriBuilder = new UriBuilder()
					.setSchemeAndAuthority("http://"+strServerAddress+":"+strServerPort)
					.setXcapRoot("/"+strServerXcapRoot+"/")
					.setDocumentSelector(documentSelector)
					.setElementSelector(elementSelector)
					.setTerminalSelector(attributeSelector);
		return uriBuilder;
	}
	
	public String getDocumentSelector() {
		String documentSelector = DocumentSelectorBuilder.getUserDocumentSelectorBuilder(
                "resource-lists", strAuthUser, strDefaultDocument).toPercentEncodedString();
		return documentSelector;
	}
	
	public String getElementSelector(String element) {
		String elementSelector = new ElementSelectorBuilder()
		.appendStepByName("resource-lists")
		.appendStepByName(element)
		.toPercentEncodedString();

		return element;
	}
	
	public String getElementSelector(String element, String attribute, String value) {
		String elementSelector = new ElementSelectorBuilder()
	        .appendStepByName("resource-lists")
	        .appendStepByAttr(element, attribute, value)
	        //.appendStepByAttr("list", "name", value)
	        .toPercentEncodedString();
		return elementSelector;
	}
	
	public String getAttributeSelector(String attribute) {
		String attributeSelector = new AttributeSelectorBuilder(attribute).toPercentEncodedString();
		return attributeSelector;
	}
	
	public String generateNewDocument() {
		String document = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
        "\n<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\">" +
        "\n<list xmlns=\"urn:ietf:params:xml:ns:resource-lists\" name=\"Ungrouped\"/>" +
        "\n</resource-lists>";
		
		return document;
	}
	
	public String getCompleteExampleDocument(){
		String document = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
		"\n<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\">" +
        	"\n<list name=\"Friends\">" +
        		"\n<entry uri=\"sip:0786346927@146.231.121.151\">"+
        			"\n<display-name>John Doe</display-name>"+
        		"\n</entry>"+
        		"\n<entry uri=\"sip:0786346928@146.231.121.151\">"+
    				"\n<display-name>Alice Wonderland</display-name>"+
    			"\n</entry>"+
    		"\n</list>"+
        "\n</resource-lists>";  
		
		return document;
	}
	
	 /*
	 * assignParams: sets the SBBs variables from the parent
	 * in:
	 * 		XcapSbbActivityContextInterface - activity context bound to the SBB
	 */
	public void assignParams(XcapSbbActivityContextInterface aci) {
		strUsername = aci.getUsernameInXcap();
		strPassword = aci.getPasswordInXcap();
		strType = aci.getTypeInXcap();
		strOp = aci.getOpInXcap();
		localName = aci.getNameInXcap();
		localNewName = aci.getNewNameInXcap();
		localNumber = aci.getNumberInXcap();
		localNewNumber = aci.getNewNumberInXcap();
		localGroup = aci.getGroupInXcap();
		localNewGroup = aci.getNewGroupInXcap();
		localTo = aci.getToInXcap();
		
		strAuthUser = "sip:"+strUsername+"@"+strServerAddress;
	}
	
	public String setAuthUser(String username, String serverAddress) {
		String authUser;
		
		authUser = "sip:"+username+"@"+serverAddress;
		return authUser;
	}
	
	/*
	 * processHTTTPRequest: creates an HTTP response event and responds to the request
	 * in: 
	 * 		ServicesStartedEvent: the event triggered by the SLEE when the SBB is loaded
	 * 		ActivityContextInterface: the activity context interface associated with the event 
	 */
	public void processHttpRequest(HttpServletRequestEvent event, String message) {
		try{
            HttpServletResponse response = event.getResponse();
            PrintWriter w = response.getWriter();
            w.print(message);
            w.flush();
            response.flushBuffer();
            tracer.info("HTTP Response sent");
		} 
		catch (IOException io) {
            io.printStackTrace();
		} 
	}
}
